package render;

import eng.Timer;
import java.awt.Graphics2D;
import java.util.List;
import light.Light;
import prim.Primitive;
import ray.RayTracer;

public class Renderer
{
    
    private int numPixelsY;
    
    private RayTracer rayEngine;
    //<editor-fold defaultstate="collapsed" desc="getRayEngine">
    public RayTracer getRayEngine()
    {
        return this.rayEngine;
    }
    //</editor-fold>
    
    private RenderBuffer renderBuffer;
    //<editor-fold defaultstate="collapsed" desc="getRenderBuffer">
    public RenderBuffer getRenderBuffer()
    {
        return this.renderBuffer;
    }
    //</editor-fold>
    
    private RenderColorMap renderMap;
    
    private int scanline;
    
    private Timer timer;
    
    public Renderer(
            int windowWidth, 
            int windowHeight, 
            int pixelsWide, 
            int pixelsTall)
    {
        // Init render dimensions
        this.numPixelsY = pixelsTall;
        
        // Init the RayTracer
        this.rayEngine = new RayTracer(
            pixelsWide, 
            pixelsTall
        );
        
        // Init the RenderBuffer
        this.renderBuffer = new RenderBuffer(
            windowWidth, 
            windowHeight, 
            pixelsWide, 
            pixelsTall
        );
        
        // Init the ColorMap for storage
        this.renderMap = new RenderColorMap(
            pixelsWide, 
            pixelsTall
        );
        
        // Set scan position to the start
        this.scanline = 0;
        
        // Init and start the timer
        this.timer = new Timer(true);
    }
    
    public void setPrimitives(List<Primitive> list)
    {
        this.rayEngine.setPrimitives(list);
    }
    
    public void setLights(List<Light> list)
    {
        this.rayEngine.setLights(list);
    }
    
    public boolean isTracingRays()
    {
        return (this.scanline < this.numPixelsY);
    }
    
    public void updateRayTraces()
    {
        this.rayEngine.traceRaysAt(
            this.scanline, 
            this.renderMap
        );
        this.renderMap.limitComponentsOfScanline(this.scanline);
        this.scanline++;
    }
    
    public void drawToPixelBuffer()
    {
        Graphics2D g = this.renderBuffer.prepareGraphics();
        if (this.scanline >= this.numPixelsY)
        {
            if (this.timer.isRunning())
            {
                double timePassed = this.timer.stop();
                String timePassStr = String.format("%.1f", timePassed);
                System.out.println("Time to render: " + timePassStr + " seconds");
            }
            this.renderMap.renderUpToScanline(this.numPixelsY, g);
            try
            {
                Thread.sleep(16L, 667);
            }
            catch (Exception e)
            {
                System.out.println(e);
                System.exit(1);
            }
        }
        this.renderBuffer.endGraphics(g);
    }
    
    public void drawToWindow()
    {
        this.renderBuffer.flip();
    }
    
    public void destroy()
    {
        this.renderMap.clearData();
    }
    
}
